﻿using System;
using System.Net;
using System.Runtime.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CloudStorage.API.Exceptions;
using Rhino.Mocks;

namespace CloudStorage.Tests.API.Exceptions
{
	[TestClass]
	public class CloudStorageExceptionTests
	{
		[TestMethod]
		public void Parameterless_Ctor()
		{
			var exception = new CloudStorageException();
			Assert.IsNotNull(exception);
		}

		[TestMethod]
		public void Message_Ctor()
		{
			var expectedMessage = "foo";

			Assert.AreEqual(expectedMessage, new CloudStorageException(expectedMessage).Message);
		}

		[TestMethod]
		public void Can_set_innerException()
		{
			var expectedMessage = "foo";
      var innerException = new Exception();

			var exception = new CloudStorageException(expectedMessage, innerException);

			Assert.AreEqual(expectedMessage, exception.Message);
			Assert.AreSame(innerException, exception.InnerException);
		}

		[TestMethod]
		public void Can_set_StatusCode()
		{
			var expectedMessage = "foo";
			var expectedStatusCode = HttpStatusCode.Unused;

			var exception = new CloudStorageException(expectedMessage, expectedStatusCode);

			Assert.AreEqual(expectedMessage, exception.Message);
			Assert.AreEqual(expectedStatusCode, exception.HttpStatusCode);
		}

		[TestMethod]
		public void Can_set_HttpStatusCode()
		{
			var innerException = new Exception();
			string message = "foo";
			HttpStatusCode httpStatusCode = HttpStatusCode.Unused;
			var exception = new CloudStorageException(message, httpStatusCode, innerException);

			Assert.IsNotNull(exception);
			Assert.AreEqual(message, exception.Message);
			Assert.AreEqual(httpStatusCode, exception.HttpStatusCode);
			Assert.AreEqual(innerException, exception.InnerException);
		}

		[TestMethod, ExpectedException(typeof(ArgumentNullException))]
		public void SerializationInfo_cannot_be_null()
		{
			// Arrange
			var cloudStorageException = new CloudStorageException("foo", HttpStatusCode.Unused, null);

			// Act
			cloudStorageException.GetObjectData(null, new StreamingContext());

			// Assert - exception
		}

		[TestMethod]
		public void Can_restore_exception()
		{
			// Arrange
			var converter = MockRepository.GenerateStub<IFormatterConverter>();
			var serializationInfo = new SerializationInfo(typeof(CloudStorageException), converter);
			var streamingContext = new StreamingContext();

			var expectedMessage = "foo";
			var exprectedHttpStatusCode = HttpStatusCode.Unused;

			var cloudStorageException = new CloudStorageException(expectedMessage, exprectedHttpStatusCode, null);

			cloudStorageException.GetObjectData(serializationInfo, streamingContext);

			// Act
			var restoredData = new CloudStorageExceptionSerializable(serializationInfo, streamingContext);

			// Assert
			Assert.AreEqual(cloudStorageException.HttpStatusCode, restoredData.HttpStatusCode);
			Assert.AreEqual(expectedMessage, restoredData.Message);
		}

		[TestMethod, ExpectedException(typeof(ArgumentNullException))]
		public void SerializationInfo_constructor_cannot_be_null()
		{
			new CloudStorageExceptionSerializable(null, new StreamingContext());
		}

		[TestMethod]
		public void GetObjectData_serializes_HttpCode()
		{
			// Arrange
			var expectedHttpStatusCode = HttpStatusCode.Unused;
			var expectedMessage = "message";

			var converter = MockRepository.GenerateStub<IFormatterConverter>();
			var serializationInfo = new SerializationInfo(typeof(CloudStorageException), converter);
			var streamingContext = new StreamingContext();

			var cloudStorageException = new CloudStorageException(expectedMessage, expectedHttpStatusCode, null);

			// Act
			cloudStorageException.GetObjectData(serializationInfo, streamingContext);

			// Assert
			var result = (HttpStatusCode)serializationInfo.GetValue("HttpStatusCode", typeof(HttpStatusCode));
			Assert.AreEqual(expectedHttpStatusCode, result);

			//Assert.AreEqual(expectedMessage, serializationInfo.GetString("Message"));
		}
	}
}